package com.andy.buyu.server.game;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

import org.apache.commons.lang3.RandomUtils;

import com.andy.buyu.server.entity.UsrGameInfo;
import com.andy.buyu.server.entity.UsrUser;
import com.andy.buyu.server.socket.SendUtil;
import com.andy.buyu.server.utils.GoConstant;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public class GameUser implements Serializable{

	private static final long serialVersionUID = 1L;

	private int sex = RandomUtils.nextInt(1, 3);
	
	private int status;
	private UsrUser user;
	private UsrGameInfo gameInfo;
	private Long id;
	private Room room;
	private int deskIndex = -1; // 位子
	private FishGame game;
	private int battery ; // 炮台类型
	
	private long lastFire; // 上次开炮时间
	// key:bullet ,value:num
	private Map<Integer,Integer> firedBullet = Maps.newHashMap(); // 已经发出的炮弹，包括普通攻击
	private int lastShell; // 最近掉落的特殊炮弹
	private int lastShellNum; // 最近掉落的特殊炮弹数量
	private long lastShellTime; // 最近掉落的特殊炮弹掉落时间
	private int shellNum; // 当前特殊炮弹数
	private long shellTime; // 获得特殊炮弹的时间
	private ScheduledFuture<?> shellTask; // 获得特殊炮弹定时任务
	private int laba; // 拉霸倍率，0-无可拉霸
	private int oldBattery;
	private int fireNum; // 当前位置已发射的炮弹数
	private int addedTime; // 增加的特殊炮台持续时间
	
	private List<KeepSeet> keepSeats = Lists.newArrayList();
	
	public GameUser() {
	}
	
	public GameUser(UsrUser user) {
		this.setUser(user);
		this.id = user.getId();
	}
	
	public String getUserName() {
		return user.getUserName();
	}

	public String getNickName() {
		return user.getNickName();
	}

	public UsrUser getUser() {
		return user;
	}

	public void setUser(UsrUser user) {
		this.user = user;
	}

	public UsrGameInfo getGameInfo() {
		return gameInfo;
	}

	public void setGameInfo(UsrGameInfo gameInfo) {
		this.gameInfo = gameInfo;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public void setRoom(Room room) {
		this.room = room;
		status = GoConstant.USER_STATUS_0;
	}

	public Room getRoom() {
		return room;
	}

	public FishGame getGame() {
		return game;
	}

	public void setGame(FishGame game) {
		this.game = game;
		if(game != null){
			this.status = GoConstant.USER_STATUS_1;
		}
	}

	public boolean isRobo() {
		return user.getRole() != null && user.getRole() == 1;
	}

	public void gameOver() {
		this.game = null;
		this.battery = GoConstant.BATTERY_TYPE_0;
		this.status = GoConstant.USER_STATUS_0;
		this.fireNum = 0;
	}
	
	public boolean isInGame(){
		return this.status == GoConstant.USER_STATUS_1;
	}

	public int getDeskIndex() {
		return deskIndex;
	}

	public void setDeskIndex(int deskIndex) {
		this.deskIndex = deskIndex;
	}

	public int getBattery() {
		return this.battery;
	}

	public void setBattery(int battery) {
		if(battery == -1 && this.battery > GoConstant.BATTERY_TYPE_2){
			// 特殊炮台切换回原基础炮
			this.battery = oldBattery;
		}else{
			this.battery = battery;
		}
	}

	public int getBatteryRate() {
		return user.getBatteryRate();
	}

	public void setBatteryRate(int batteryRate) {
		this.user.setBatteryRate(batteryRate);
	}

	public boolean checkFire(int battery2) {
		long now = System.currentTimeMillis();
		if(battery2 > GoConstant.BATTERY_TYPE_1){
			// 检测特殊炮弹是否足够，时间是否已超（多加2秒抵消网络传输）
			if(this.shellNum <= 0 || (now-this.shellTime) > GameConf.getSpecialBullet(battery2).getLimitTime()+2*1000+addedTime){
				return false;
			}
		}else{
//			if(now - this.lastFire < 10) return false;
		}
		return true;
	}

	public void fire(int battery2) {
		this.lastFire = System.currentTimeMillis();
		this.shellNum--;
		fireNum++;
		
		// 如果特殊炮已经打完了，切换原基础炮台
		if(battery2 > GoConstant.BATTERY_TYPE_1 && this.shellNum <= 0){
			if(shellTask != null){
				// 取消定时
				shellTask.cancel(false);
			}
			this.shellTime = 0;
			this.addedTime = 0;
			this.battery = oldBattery;
		}
	}
	
	/**
	 * 检查是否可以攻击
	 * @param type 炮弹类型
	 * @param scriptId
	 * @return
	 */
	public boolean catchFish(int bullet,Integer scriptId) {
		Integer num = firedBullet.get(bullet);
		if(num == null || num <= 0){
			return false;
		}
		firedBullet.put(bullet, --num);
		return true;
	}

	public void addBullet(Integer bullet,int count) {
		firedBullet.put(bullet,firedBullet.getOrDefault(bullet, 0)+count);
	}

	public int getShellNum() {
		return shellNum;
	}

	public void setShellNum(int shellNum) {
		this.shellNum = shellNum;
		this.shellTime = System.currentTimeMillis();
		
		// 定时重置
		if(shellTask != null){
			shellTask.cancel(false);
		}
		// 由客户端控制切换，服务端只做校验
//		shellTask = TimerManager.schedule(()->{
//			// 清理
//			this.shellNum = 0;
//			this.shellTime = 0;
//			this.battery = oldBattery;
//			SendUtil.send203(this);
//			return null;
//		}, GoConstant.SHELL_DURA[battery-10]*1000);
	}

	public int getLaba() {
		return laba;
	}

	public void setLaba(int laba) {
		this.laba = laba;
	}

	public int getSex() {
		return sex;
	}
	
	public void addKeepSeat(KeepSeet seet){
		keepSeats.add(seet);
	}

	public void clearKeepSeat(){
		for(KeepSeet kp:keepSeats){
			Room kroom = Global.getRoom(kp.getRoomId());
			kroom.removeKeepSeat(kp);
			
			SendUtil.send103(room, kp.getIndex());
		}
		keepSeats.clear();
	}

	/**
	 * 切换特殊炮
	 * @param battery2
	 * @return 
	 */
	public boolean exchangeBattery(int battery2) {
		if(lastShell == battery2 && System.currentTimeMillis() - lastShellTime < 10*1000){
			// 切换特殊炮台，保存原基础炮台
			if(this.battery < GoConstant.BATTERY_TYPE_2){
				this.oldBattery = this.battery;
			}
			this.battery = battery2;
			this.addedTime = 0;
			setShellNum(lastShellNum);
			return true;
		}
		return false;
	}

	/**
	 * 掉落炮弹
	 * @param curShell
	 */
	public boolean dropShell(int battery2 ) {
		if(this.battery >= 14 && battery2 < this.battery) {
			return false;
		}
		this.lastShell = battery2;
		this.lastShellTime = System.currentTimeMillis();
		this.lastShellNum = GameConf.getSpecialBullet(battery2).tryNum();
		return true;
	}
	
	public int getLastShell() {
		return lastShell;
	}
	public int getLastShellNum() {
		return lastShellNum;
	}

	public int fireNum() {
		return fireNum;
	}
	
	/**
	 * 增加特殊炮弹额外时间
	 * @param val
	 */
	public void addedTime(int val) {
		this.addedTime += val;
	}

}
